#include "udiskupgrade.h"
#include "udisk.h"
#include "constants.h"
#include "qterminal.h"
#include "_def_p.h"
#include <QThread>
#include <QDebug>
#include <QDir>

class Worker : public QObject
{
    Q_OBJECT
public:
    Worker();
    ~Worker();

signals:
    void upgrade(const QString &path);
    void enumUpgradePackages();
    void done(const QString &info, bool restart = false);
    void done(const QStringList &files);

public slots:
    void onUpgrade(const QString &path);
    void onEnumUpgradePackages();
};

struct UdiskUpgradePrivate
{
    QThread m_thread;
    Worker m_worker;
};

UdiskUpgrade::UdiskUpgrade(QObject *parent) : IUpgrade(parent), d(new UdiskUpgradePrivate)
{
    connect(&d->m_worker, SIGNAL(done(const QString &, bool)), this, SIGNAL(done(const QString &, bool)));
    connect(&d->m_worker, SIGNAL(done(const QStringList &)), this, SIGNAL(done(const QStringList &)));

    d->m_worker.moveToThread(&d->m_thread);
    d->m_thread.start();
}

UdiskUpgrade::~UdiskUpgrade()
{
    d->m_thread.quit();
    d->m_thread.wait();
    delete d;
}

void UdiskUpgrade::upgrade(const QString &path)
{
    emit d->m_worker.upgrade(path);
}

void UdiskUpgrade::enumUpgradePackages()
{
    emit d->m_worker.enumUpgradePackages();
}

Worker::Worker()
{
    connect(this, &Worker::enumUpgradePackages, this, &Worker::onEnumUpgradePackages);
    connect(this, &Worker::upgrade, this, &Worker::onUpgrade);
}

Worker::~Worker()
{
    disconnect(this, &Worker::enumUpgradePackages, this, &Worker::onEnumUpgradePackages);
    disconnect(this, &Worker::upgrade, this, &Worker::onUpgrade);
}

void Worker::onUpgrade(const QString &path)
{  
    QString message;
    QTerminal terminal(TOKEN);
    Udisk disk(UsbMountDir);

    bool ret = disk.mount();
    if (!ret)
    {
        message = disk.error();
    }

    ret = ret && terminal.runAsAdmin(QString("dpkg -i %1/%2").arg(disk.mountDir()).arg(path), &message);
    emit done(ret ? tr("Please restart the system to complete the whole upgrade.") : tr("Upgrade fail."), ret);
}

void Worker::onEnumUpgradePackages()
{
    QString message;
    Udisk disk(UsbMountDir);

    bool ret = disk.mount(true);
    if (!ret)
    {
        emit done(disk.error());
        return;
    }

    QStringList fileList;
    QDir dir(disk.mountDir());
    if (ret && dir.exists())
    {
        fileList = dir.entryList(QStringList() << "*.deb", QDir::Files, QDir::Name);
    }

    emit done(fileList);
}

#include "udiskupgrade.moc"
